#include "BotTest.h"

#include <vector>
#include <time.h>
#include <stdlib.h>
#include <algorithm>
#include "../Model/GameModel.h"
#include "../Interface/Player.h"
#include "../Connector/Connector.h"
#include "../Logger/Logger.h"



int BotTest::BotTestNum_ = 1000;

int BotTest::getFavourite()
{
  log("getFavourite");
  int favouriteProb = 0;
  int favourite = 0;
  for (int i = 0; i != playersNumber_; ++i)
  {
    if (probabilities_[i] > favouriteProb)
    {
      favouriteProb = probabilities_[i];
      favourite = i;
    }
  }
  return favourite;
}

int BotTest::getPlayerToMove(int a, int b)
{
  //log(a);
  //log(b);
  log("getPlayerToMove a, b");
  if ((a < 0) || (a >= playersNumber_) || (b < 0) || (b >= playersNumber_))
  {
    return -1;
  }
  int prob1 = probabilities_[a] * 10;
  int prob2 = probabilities_[b] * 10;
  int sum = a + b;

  if (sum == 0)
  {
    return a;
  }


  int move = rand() % sum;

  if (move < prob1)
  {
    return a;
  }
  else
  {
    return b;
  }
}

int BotTest::getPlayerToMove()
{
  log("getPlayerToMove");
  std::vector<int> coeff;
  coeff.resize(playersNumber_);
  int sum = 0;

  for (int i = 0; i != playersNumber_; ++i)
  {
     coeff[i] = probabilities_[i] * 10;
     log("coeff");
     //log(i);
     //log(coeff[i]);
     sum += coeff[i];
  }

  if (sum == 0)
  {
    return 0;
  }


  //log(sum);
 // srand(time(0));
  int move = rand() % sum;
  log("move");
  //log(move);
  int i = 0;
  int k = 0;
  //for (int i = 0, k = 0; i <= move; i += coeff[k])
  do
  {
    //log("k");
    //log(k);
    //log("i");
    //log(i);
    i += coeff[k];
    if ((i > move) || (k >= playersNumber_))
    {
      return k;
    }
    else
    {
      k++;
    }
  } while(i <= move);
  return -1;
}

BotTest::BotTest(): playersNumber_(0)
{
}

BotTest::BotTest(int playersNumber): playersNumber_(playersNumber)
{
}

BotTest::BotTest(int playersNumber, const std::vector<double> &prob): playersNumber_(playersNumber)
{
  probabilities_.resize(playersNumber_);
  /*for (int i = 0; i != playersNumber_; ++i)
  {
    probabilities_[i] = prob[i];
  }*/
  std::copy(prob.begin(), prob.end(), probabilities_.begin());
}

void BotTest::setPlayersNumber(int playersNumber)
{
  playersNumber_ = playersNumber;
}

void BotTest::setProbabilities(const std::vector<double> &prob)
{
  playersNumber_= prob.size();
  probabilities_.resize(playersNumber_);
  for (int i = 0; i != playersNumber_; ++i)
  {
    probabilities_[i] = prob[i];
  }
  //log("ok1", CRITICAL);
  //log(playersNumber_);
 // std::copy(prob.begin(), prob.end(), probabilities_.begin());
}


void BotTest::testOneGame()
{
  //log("testOneGame" , CRITICAL);
  GameModel model;
  Connector connector(model);
  Player players[playersNumber_];
  std::string name = "";
  int error = 0;
  time_t connectTime = time(0);
  for (int i = 0; i != playersNumber_; ++i)
  {
    players[i].setConnector(connector);
    players[i].connect(name, connectTime, error);
  }
  connector.startGame(true);

  bool exit = false;
  int favourite = getFavourite();
  int i = 0;
  while (model.isGameStarted())
  {
    exit = false;
    if (model.getArrowsInsideFlag() != 0)
    {
      log("move is\n");
      int k = getPlayerToMove();
     // log(k);
      connector.getTotem(players[k].getSeat());
      i = k;
    }
    players[i].openCard();

    for (int j = 0; j != playersNumber_; j++)
    {
      for (int k = 0; k != playersNumber_; k++)
      {
        if ((j != k) &&
            (model.getTopCardID(players[j].getSeat()) != -1) &&
            (model.getTopCardID(players[j].getSeat()) == (model.getTopCardID(players[k].getSeat()))))
        {
          int move = getPlayerToMove(j, k);
          players[move].getTotem();
          exit = true;
          break;
        }
      }
      if (exit)
      {
        break;
      }
    }
    ++i;
    i = i % playersNumber_;
  }
  if (model.getWhoIsWinner() == 0)
  {
    log("Draw", CRITICAL);
    return;
  }
  bool check = (model.getWhoIsWinner() == players[favourite].getSeat());
  //showError(check);
  checkError(check);
  if (!check)
  {
    /*log("and the winner is", CRITICAL);
    log(model.getWhoIsWinner(), CRITICAL);
    log(players[favourite].getSeat(), CRITICAL);
    log(favourite, CRITICAL);*/
  }
  else
  {
/*
    log("and the winner is", CRITICAL);
    log(model.getWhoIsWinner(), CRITICAL);
    log(players[favourite].getSeat(), CRITICAL);
    log(favourite, CRITICAL);
    //log("OK", CRITICAL);*/
  }
}

void BotTest::test()
{
  //for (int i = 0; i != BotTestNum_; ++i)
  srand(time(0));
  while(numOk_ + numFail_ < BotTestNum_)
  {
    //log("Test", CRITICAL);
    testOneGame();
  }
 // showError(getPlayerToMove() != -1);
}
